package main

import (
	"database/sql"
	//_ "github.com/lib/pq"              // enable support for Postgres
	//_ "github.com/go-sql-driver/mysql" // enable support for MySQL

	"fmt"
	"github.com/gotk3/gotk3/gdk"
	"github.com/gotk3/gotk3/glib"
	"github.com/gotk3/gotk3/gtk"
	"log"

	_ "image/png" // register PNG decoder
)

// IDs to access the tree view columns by
const (
	//COLUMN_ICON = iota
	COLUMN_TEXT = iota //导航栏 现在只有一列，文本
)

var gdb *sql.DB
var gtvw *gtk.TreeView     //记事本 目录导航栏
var gtkmenu *gtk.Menu      //弹出式菜单
var gtStore *gtk.TreeStore //导航栏数据store
var cx, cy int             //坐标
var gwin *gtk.Window

func ecp(e error) {
	if e != nil {
		log.Fatal("error:", e)
	}
}

func main() {

	gtk.Init(nil)
	win, err := gtk.WindowNew(gtk.WINDOW_TOPLEVEL)
	ecp(err)
	win.SetTitle("错题本 0.0.1")
	win.Connect("destroy", func() {
		gtk.MainQuit()
	})
	gwin = win
	scrollwin, err := gtk.ScrolledWindowNew(nil, nil)
	scrollwin.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
	scrollwin.SetSizeRequest(100, 100)
	//fBoxl,err :=gtk.BoxNew(gtk.ORIENTATION_VERTICAL,1)

	setupTopitem(scrollwin, []string{"语文", "数学", "英语", "生物", "化学", "历史", "政治"})

	/*fBoxl.SetMarginEnd(5);fBoxl.SetMarginStart(5)
	fBoxl.SetMarginTop(5);fBoxl.SetMarginBottom(5)
	fBoxl.ShowAll()*/
	setuppopmenu()

	//
	rscrollwin, err := gtk.ScrolledWindowNew(nil, nil)
	rscrollwin.SetPolicy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
	rscrollwin.SetSizeRequest(600, 100)
	fBoxr, err := gtk.BoxNew(gtk.ORIENTATION_VERTICAL, 1)
	lbl, err := gtk.LabelNewWithMnemonic("列表")
	fBoxr.PackStart(lbl, false, false, 5)
	fBoxr.ShowAll()
	rscrollwin.Add(fBoxr)

	fPaned, err := gtk.PanedNew(gtk.ORIENTATION_HORIZONTAL)
	fPaned.SetTooltipText("")
	fPaned.SetBorderWidth(3)
	fPaned.Add1(scrollwin)
	fPaned.Add2(rscrollwin)

	win.Add(fPaned)
	win.SetDefaultSize(800, 600) //设置主窗口宽高像素
	win.SetPosition(gtk.WIN_POS_CENTER)
	fPaned.ShowAll()
	win.ShowAll()
	//db
	gdb = opendb("./ctb.sqlite3")
	defer gdb.Close()
	createtable(gdb)
	//
	var anode ANODE

	readimgfrombuf(nil, "./8.png", &anode.b)
	anode.Title = "测试title"
	insert2mu(gdb, anode)
	//
	gtk.Main()

}

func setupTopitem(scrollwin *gtk.ScrolledWindow, stitle []string) {
	tre, tss := setupTreeView("科目 知识点")
	for _, b := range stitle {
		addRow(tss, b)
	}
	gtvw = tre

	selection, err := tre.GetSelection()
	ecp(err)
	selection.SetMode(gtk.SELECTION_SINGLE)
	selection.Connect("changed", treeSelectionChangedCB)
	gtvw.Connect("button-release-event", tvclickedfun, gtkmenu) //button_press_event  ..导致不能及时显示当前点击节点，总是显示上一次点击节点
	scrollwin.Add(tre)

}
func tvclickedfun(tv *gtk.TreeView, evt *gdk.Event, menu *gtk.Menu) {
	event := gdk.EventButtonNewFromEvent(evt)
	if event.Type() == gdk.EVENT_BUTTON_PRESS { //单击
		fmt.Printf("单击, ")
	} else if event.Type() == gdk.EVENT_DOUBLE_BUTTON_PRESS { //双击
		fmt.Printf("双击, ")
	}
	fmt.Println("button = ", event.Button())
	if event.Button() == 1 {
		fmt.Printf("左键, ")
	} else if event.Button() == 2 {
		fmt.Printf("中间键, ")
	} else if event.Button() == 3 {
		fmt.Printf("右键, ")
		cx, cy = int(event.X()), int(event.Y())
		//在光标位置弹出菜单
		gtkmenu.PopupAtPointer(evt)
	}
	showclickitem(tv)
	fmt.Println("坐标:", event.X(), event.Y())

}
func buildMenu(m *gtk.Menu, label string, f interface{}, userData ...interface{}) {
	item, err := gtk.MenuItemNewWithLabel(label)
	ecp(err)
	item.Show()
	item.Connect("activate", f, userData)
	m.Append(item)
}
func setuppopmenu() {
	var err error
	gtkmenu, err = gtk.MenuNew()
	ecp(err)
	//item, _ := gtk.MenuItemNewWithLabel("追加节点")    ;	item.Show()
	//item.Connect("activate", tvw_append, gtvw) ;	gtkmenu.Append(item)
	item, _ := gtk.MenuItemNewWithLabel("前插节点")
	item.Show()
	item.Connect("activate", tvw_insert, gtvw)
	gtkmenu.Append(item)
	item, _ = gtk.MenuItemNewWithLabel("后插节点")
	item.Show()
	item.Connect("activate", tvw_insertnext, gtvw)
	gtkmenu.Append(item)
	item, _ = gtk.MenuItemNewWithLabel("插入子节点")
	item.Show()
	item.Connect("activate", tvw_insertchild, gtvw)
	gtkmenu.Append(item)
	item, _ = gtk.MenuItemNewWithLabel("重命名节点")
	item.Show()
	item.Connect("activate", tvw_rename, gtvw)
	gtkmenu.Append(item)
	item, _ = gtk.MenuItemNewWithLabel("删除节点")
	item.Show()
	item.Connect("activate", tvw_delete, gtvw)
	gtkmenu.Append(item)

}
func tvw_insert(mi *gtk.MenuItem, tvw *gtk.TreeView) {
	selection, _ := tvw.GetSelection()
	tvmodel, _ := tvw.GetModel()

	var iter *gtk.TreeIter
	var model gtk.ITreeModel
	var ok bool
	model, iter, ok = selection.GetSelected()

	if ok {
		firstite, ok := model.(*gtk.TreeModel).GetIterFirst()
		if ok {
		}
		v0, _ := tvmodel.GetValue(firstite, 0)
		s, _ := v0.GetString()
		log.Printf("选中节点的firstNode :%s\n", s)

		tpath, err := model.(*gtk.TreeModel).GetPath(iter)
		v1, err := tvmodel.GetValue(iter, 0)
		ecp(err)
		col1, err := v1.GetString()
		log.Printf("选中 :%s,%s\n", tpath, col1)

		//addnode(gtStore,firstite,tpath.GetDepth(),nil)
		addbeforenode(gtStore, nil, iter, "前插节点")
	}

}
func tvw_insertnext(mi *gtk.MenuItem, tvw *gtk.TreeView) {

	selection, _ := tvw.GetSelection()
	tvmodel, _ := tvw.GetModel()

	var iter *gtk.TreeIter
	var model gtk.ITreeModel
	var ok bool
	model, iter, ok = selection.GetSelected()

	if ok {
		firstite, _ := model.(*gtk.TreeModel).GetIterFirst()
		v0, _ := tvmodel.GetValue(firstite, 0)
		s, _ := v0.GetString()
		log.Printf("选中节点的firstNode :%s\n", s)

		tpath, err := model.(*gtk.TreeModel).GetPath(iter)
		v1, err := tvmodel.GetValue(iter, 0)
		ecp(err)
		col1, err := v1.GetString()
		log.Printf("选中 :%s,%s\n", tpath, col1)
		addafternode(gtStore, nil, iter, "后新节点")

	}
}
func tvw_insertchild(mi *gtk.MenuItem, tvw *gtk.TreeView) {
	selection, _ := tvw.GetSelection()
	tvmodel, _ := tvw.GetModel()

	var iter *gtk.TreeIter
	var model gtk.ITreeModel
	var ok bool
	model, iter, ok = selection.GetSelected()

	if ok {
		firstite, ok := model.(*gtk.TreeModel).GetIterFirst()
		if ok {
		}
		v0, _ := tvmodel.GetValue(firstite, 0)
		s, _ := v0.GetString()
		log.Printf("选中节点的firstNode :%s\n", s)

		tpath, err := model.(*gtk.TreeModel).GetPath(iter)
		v1, err := tvmodel.GetValue(iter, 0)
		ecp(err)
		col1, err := v1.GetString()
		log.Printf("选中 :%s,%s\n", tpath, col1)
		//addafternode(gtStore,nil,iter,"新节点")
		addSubRow(gtStore, iter, "新子节点")
	}
}
func tvw_rename(mi *gtk.MenuItem, tvw *gtk.TreeView) {
	selection, _ := tvw.GetSelection()
	//tvmodel, _ := tvw.GetModel()

	var iter *gtk.TreeIter
	//var model gtk.ITreeModel
	var ok bool

	_, iter, ok = selection.GetSelected()
	x0, y0 := gwin.GetPosition()
	if ok {
		// Set the contents of the tree store row that the iterator represents
		//err := treeStore.SetValue(i, COLUMN_TEXT, []interface{}{a,b, text})
		dg, _ := gtk.DialogNew()
		dg.SetCanFocus(true)
		dg.SetVisible(true)
		//dg.SetPosition(gtk.WIN_POS_MOUSE)

		dg.Move(x0+cx+50, y0+cy+50)
		dg.SetTitle("请输入节点名")
		//wg,_:=tvw.GetToplevel()
		dg.SetKeepAbove(true)
		bx, _ := dg.GetContentArea()
		eb, _ := gtk.EntryBufferNew("", -1)
		en, _ := gtk.EntryNewWithBuffer(eb)
		en.Show()
		en.SetCanDefault(true)
		bx.PackStart(en, true, false, 5)

		yesbn, _ := gtk.ButtonNewWithLabel("确定")
		yesbn.Show()
		cancelbn, _ := gtk.ButtonNewWithLabel("放弃")
		cancelbn.Show()
		yesbn.Connect("clicked", func() {
			fmt.Println("确定按钮被按下")
			dg.Close()
		})
		cancelbn.Connect("clicked", func() {
			fmt.Println("放弃按钮被按下")
			eb.SetText("") //清空
			dg.Close()
		})
		bx2, _ := gtk.BoxNew(gtk.ORIENTATION_HORIZONTAL, 25)
		bx2.ShowAll()
		bx2.PackStart(yesbn, false, false, 5)
		bx2.PackStart(cancelbn, false, false, 5)
		bx.PackStart(bx2, false, false, 5)

		dg.Add(bx)
		dg.Run()
		dg.Destroy()
		if eb.GetLength() > 0 {
			txt, _ := eb.GetText()
			gtStore.SetValue(iter, COLUMN_TEXT, txt)
		}

	}

}

func tvw_delete(mi *gtk.MenuItem, tvw *gtk.TreeView) {

}

//仅在顶级节点追加节点
func tvw_append(mi *gtk.MenuItem, tvw *gtk.TreeView) {
	addRow(gtStore, "新顶级节点") //panic: interface conversion: gtk.ITreeModel is *gtk.TreeModel, not *gtk.TreeStore
}

// Add a column to the tree view (during the initialization of the tree view)
// We need to distinct the type of data shown in either column.
func createTextColumn(title string, id int) *gtk.TreeViewColumn {
	// In this column we want to show text, hence create a text renderer
	cellRenderer, err := gtk.CellRendererTextNew()
	ecp(err)
	// Tell the renderer where to pick input from. Text renderer understands the "text" property.
	column, err := gtk.TreeViewColumnNewWithAttribute(title, cellRenderer, "text", id)
	ecp(err)
	return column
}
func createImageColumn(title string, id int) *gtk.TreeViewColumn {
	// In this column we want to show image data from Pixbuf, hence
	// create a pixbuf renderer
	cellRenderer, err := gtk.CellRendererPixbufNew()
	ecp(err)
	// Tell the renderer where to pick input from. Pixbuf renderer understands the "pixbuf" property.
	column, err := gtk.TreeViewColumnNewWithAttribute(title, cellRenderer, "pixbuf", id)
	ecp(err)
	return column
}

// Creates a tree view and the list store that holds its data
func setupTreeView(title string) (*gtk.TreeView, *gtk.TreeStore) {
	treeView, err := gtk.TreeViewNew()
	ecp(err)
	//treeView.AppendColumn(createTextColumn("Version", COLUMN_VERSION))
	treeView.AppendColumn(createTextColumn(title, COLUMN_TEXT))

	// Creating a list store. This is what holds the data that will be shown on our tree view.
	tStore, err := gtk.TreeStoreNew(glib.TYPE_STRING)
	ecp(err)
	gtStore = tStore
	treeView.SetModel(tStore) //为何 把treestore传过去，而取不出？

	return treeView, tStore
}

// Handle selection
func treeSelectionChangedCB(selection *gtk.TreeSelection) {
	var iter *gtk.TreeIter
	var model gtk.ITreeModel
	var ok bool
	model, iter, ok = selection.GetSelected()
	if ok {
		tpath, err := model.(*gtk.TreeModel).GetPath(iter)
		if err != nil {
			log.Printf("treeSelectionChangedCB: Could not get path from model: %s\n", err)
			return
		}
		log.Printf("treeSelectionChangedCB: selected path: %s\n", tpath)
	}

}

// Append a toplevel row to the tree store for the tree view
func addRow(treeStore *gtk.TreeStore, text string) *gtk.TreeIter {
	return addSubRow(treeStore, nil, text)
}

// Append a sub row to the tree store for the tree view
func addSubRow(treeStore *gtk.TreeStore, iter *gtk.TreeIter, text string) *gtk.TreeIter {
	// Get an iterator for a new row at the end of the list store
	i := treeStore.Append(iter)
	// Set the contents of the tree store row that the iterator represents
	//err := treeStore.SetValue(i, COLUMN_TEXT, []interface{}{a,b, text})      ;ecp(err)
	err := treeStore.SetValue(i, COLUMN_TEXT, text)
	ecp(err)
	return i
}
func addbeforenode(treeStore *gtk.TreeStore, parent *gtk.TreeIter, sibling *gtk.TreeIter, text string) *gtk.TreeIter {
	i := treeStore.InsertBefore(parent, sibling)
	err := treeStore.SetValue(i, COLUMN_TEXT, text)
	ecp(err)
	return i
}
func addafternode(treeStore *gtk.TreeStore, parent *gtk.TreeIter, sibling *gtk.TreeIter, text string) *gtk.TreeIter {
	i := treeStore.InsertAfter(parent, sibling)
	err := treeStore.SetValue(i, COLUMN_TEXT, text)
	ecp(err)
	return i
}
func addnode(treeStore *gtk.TreeStore, parent *gtk.TreeIter, position int, text string) *gtk.TreeIter {
	i := treeStore.Insert(parent, position)
	err := treeStore.SetValue(i, COLUMN_TEXT, text)
	ecp(err)
	return i
}
func showclickitem(tview *gtk.TreeView) {
	selection, err := tview.GetSelection()
	ecp(err)
	tvmodel, err := tview.GetModel()

	var iter *gtk.TreeIter
	var model gtk.ITreeModel
	//var store *gtk.ListStore
	var ok bool
	//store = (*gtk.ListStore)(tvmodel)
	model, iter, ok = selection.GetSelected()
	if ok {
		tpath, err := model.(*gtk.TreeModel).GetPath(iter)
		v1, err := tvmodel.GetValue(iter, 0)
		ecp(err)
		col1, err := v1.GetString()
		log.Printf("选中 :%s,%s\n", tpath, col1)
	}
}

/*
//创建pixbuf，指定大小（宽度和高度
    pixbuf, _ := gdkpixbuf.NewPixbufFromFileAtScale("image/head.png", w-10, h-10, false)

    //通过pixbuf新建image
    image := gtk.NewImageFromPixbuf(pixbuf)

    //释放pixbuf资源
    pixbuf.Unref()

    //按钮设置image
    button2.SetImage(image)

    //按钮信号处理
    button2.Connect("clicked", func() {
        fmt.Println("按钮2被按下")
    })
*/
